#include<iostream>
#include<vector>
#include <sstream>
#include <math.h>
#include<cstdlib>
#include<time.h>
using namespace std;

#define forn(i,n) for(typeof(n) i=0;i<(n);i++)
#define forsn(i,s,n) for(typeof(n) i=s;i<(n);i++)
#define forall(it,X) for( typeof((X).begin()) it = (X).begin() ; it!=(X).end() ; it++ )
#define fornr(i,n) for(int i=(n)-1;i>=0;i--)
#define O(o) contador+=(o);
long long int contador=0;

typedef vector<int> vint;
typedef vector<vint> vvint;

vvint mul(const vvint& A, const vvint& B){
	int n = A.size();
	vvint res(n,vint(n,0)); O(n*n)
	forn(i,n) forn(j,n) forn(k,n) res[i][j] += A[i][k] * B[k][j];
	O(2*n*n*n)
	return res;
}

void complemento(vvint& A){

	/* creo una matriz complemento igual a la original, 
	 * con todos sus elementos, salvo la diagonal, negados */

	int n = A.size();
	forn(i,n) forn(j,n) A[i][j] = i!=j && !A[i][j];
	O(2*n*n)
}

bool K3(const vvint& A, const vvint& A2, int i){

	/* Calculo si elemento i-esimo de la diagonal de la matriz A elevada al cubo 
	 * es 0 (no existen ciclos de largo 3 que contengan ese nodo) 
	 * o no (si existe al menos uno de estos ciclos).
	 * Devuelvo verdadero si existe alguno y falso en caso contrario */

	forn(k,A.size()) if(A2[i][k] && A[k][i]){O(2) return true;}
	return false;
}

vint grupo(const vvint& A){

	/* Calculo el cuadrado de la matriz de adyacencia
	 * (todos los caminos de largo 2) */

	vvint A2 = mul(A,A);

	int n = A.size();
	vint g(3,0);
	int i, j, k;
	O(6)

	/* Calculo el K3 lexicograficamente menor */

	for(i=0; i<n-2 && !K3(A,A2,i); i++); g[0] = i==n-2?0:i+1;
	for(j=i+1; j<n-1 && !(K3(A,A2,j) && A2[j][i] && A[j][i]); j++); g[1] = j==n-1?0:j+1;
	for(k=j+1; k<n && !(K3(A,A2,k) && A[k][j] && A[k][i]); k++); g[2] = k==n?0:k+1;
	O(4*k)

	/* Devuelvo el resultado */

	return g;
}

string cw(vvint& A){

	/* Si el grupo no tiene al menos 3 personas, 
	 * no se puede armar un grupo de 3 */
	O(2)
	if(A.size()<3) return "0 0 0 0 0 0";

	/* Calculo el grupo Coppersmith */

	vint gc = grupo(A);

	/* Calculo el grupo Winograd */

	complemento(A);
	vint gw = grupo(A);
	O(6)
	/* Devuelvo el resultado */

	ostringstream res;
	res << gc[0] << " " << gc[1] << " " << gc[2] << " " << gw[0] << " " << gw[1] << " " << gw[2]; O(12)
	return res.str();
}

int main(int argc, char** argv){ 
	int n;
	while(cin >> n && n!=-1){

		/* Para cada instancia del problema, genero la 
		 * matriz de adyacencia a partir de la entrada */

		vvint A(n,vint(n,0));
		forn(i,n){
			int m; cin >> m;
			forn(j,m){
				int k; cin >> k;
				A[i][k-1] = 1;
				A[k-1][i] = 1;
			}
		}
				
		clock_t start,end;
		if(argc>1 && string(argv[1])=="time"){ //si el primer argumento es "time" mido tiempos..
			float secs=argc>2?secs=atof(argv[2]):0.5; //lo ejecuto hasta que tarde al menos secs segundos, para tener presicion (0.5 por default)
			int tries=argc>3?tries=atoi(argv[3]):1; // tomo el tiempo times veces por dato de entrada, para disminuir el error
			forn(tr,tries){
				start = clock(); //guardo el tiempo
				long long int cont=0;
					while((double)(clock()-start)/CLOCKS_PER_SEC<secs){ //evaluo la funcion hasta que tarde al menos secs
						cw(A);
						cont++;
					}
				end = clock(); //guardo el tiempo de finalizacion
				double tiempo=(double)(end-start)/(CLOCKS_PER_SEC*cont);
				//el tiempo total de evaluacion es lo_que_tardo/cantidad_de_veces_que_lo_llamo
				printf("%.8f ",tiempo); //imprimo el resultado con 8 decimales de presicion
			}
			cout << endl;
			
		}else if(argc>1 && string(argv[1])=="count"){ // si el argumento es "count", cuento cantidad de operaciones..
			contador=0;
			cw(A);
			cout << contador << endl; //imprimo la cuenta
			
		}else{
			cout << cw(A) << endl;
		}
	}

	return 0;
}
